using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

namespace LS.GameKit.SequenceAnimate
{
    public class SequenceRendererUtility
    {
        public static SequenceRenderer CreateRenderer(Component component,string visulsElementName = null)
        {
            if(component is UIDocument)
            {
                return new UIDocumentRenderer(component as UIDocument);
            }
            else if(component is UnityEngine.UI.Image)
            {
                return new ImageRenderer(component as UnityEngine.UI.Image);
            }
            else if(component is SpriteRenderer)
            {
                return new UnitySpriteRenderer(component as SpriteRenderer);
            }
            else if(component is MeshRenderer)
            {
                return new UnityMeshRenderer(component as MeshRenderer);
            }
            else if (component is SkinnedMeshRenderer)
            {
                return new UnityMeshRenderer(component as SkinnedMeshRenderer);
            }
            else
            {
                return null;
            }
        }

        public static SequenceRenderer CreateRenderer(Material material)
        {
            return new MaterialRenderer(material);
        }
    }

    public abstract class SequenceRenderer : IDisposable
    {
        public abstract bool IsAvailable { get; }
        public abstract void Dispose();
        public abstract void SetImage(Sprite sprite);
    }

    public class ImageRenderer : SequenceRenderer
    {
        private UnityEngine.UI.Image m_Image;

        public override bool IsAvailable => m_Image != null;

        public ImageRenderer(UnityEngine.UI.Image image)
        {
            m_Image = image;
        }

        public override void SetImage(Sprite sprite)
        {
            if (m_Image != null)
                m_Image.sprite = sprite;
        }

        public override void Dispose()
        {
            m_Image = null;
        }
    }

    public class UnitySpriteRenderer : SequenceRenderer
    {
        private SpriteRenderer m_Sprite;

        public override bool IsAvailable => m_Sprite != null;

        public UnitySpriteRenderer(SpriteRenderer spriteRenderer)
        {
            m_Sprite = spriteRenderer;
        }

        public override void SetImage(Sprite sprite)
        {
            if(m_Sprite != null)
                m_Sprite.sprite = sprite;
        }

        public override void Dispose()
        {
            m_Sprite = null;
        }
    }

    public class UIDocumentRenderer : SequenceRenderer
    {
        private UIDocument m_Document;
        private VisualElement m_Element;

        public override bool IsAvailable => m_Document != null;

        public UIDocumentRenderer(UIDocument document)
        {
            m_Document = document;
        }

        public override void Dispose()
        {
            m_Document = null;
        }

        public void ReSearchElement(string elementName)
        {
            m_Element = m_Document?.rootVisualElement?.Q(elementName);
        }

        public override void SetImage(Sprite sprite)
        {
            if(m_Element != null)
                m_Element.style.backgroundImage = new StyleBackground(sprite);
        }
    }

    public class UnityMeshRenderer : SequenceRenderer
    {
        private MeshRenderer m_Mesh;
        private SkinnedMeshRenderer m_Skinned;

        public override bool IsAvailable => m_Mesh != null || m_Skinned != null;

        public UnityMeshRenderer(MeshRenderer renderer)
        {
            m_Mesh = renderer;
            m_Skinned = null;
        }

        public UnityMeshRenderer(SkinnedMeshRenderer renderer)
        {
            m_Mesh = null;
            m_Skinned = renderer;
        }

        public override void Dispose()
        {
            m_Mesh = null;
            m_Skinned = null;
        }

        public override void SetImage(Sprite sprite)
        {
            if (m_Mesh != null)
                m_Mesh.material.mainTexture = sprite.texture;

            if(m_Skinned != null)
                m_Skinned.material.mainTexture = sprite.texture;
        }
    }

    public class MaterialRenderer : SequenceRenderer
    {
        private Material m_Material;

        public override bool IsAvailable => m_Material != null;

        public MaterialRenderer(Material material)
        {
            m_Material = material;
        }

        public override void Dispose()
        {
            m_Material = null;
        }

        public override void SetImage(Sprite sprite)
        {
            if (m_Material != null)
                m_Material.mainTexture = sprite.texture;
        }
    }
}
